package com.game.shudu;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;

import java.util.HashMap;

/**
 * 棋盘界面
 */
public class PuzzleView extends View {
    private float width;
    private float height;
    private int borderTopSize = 100;
    private int borderLeftSize = 20;
    private int funTop = 20;//选项与棋盘的上间距
    private int selX;
    private int selY;
    private Rect selRect = new Rect();

    private static final String TAG = "PuzzleView";
    private final Game game;

    private static final String SELX = "selX";
    private static final String SELY = "selY";
    private static final String VIEW_STATE = "viewState";
    private static final int ID = 14;

    public PuzzleView(Context context) {
        super(context);
        this.game = (Game) context;
        setFocusable(true);
        setFocusableInTouchMode(true);
        setId(ID);
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        Parcelable p = super.onSaveInstanceState();
        Bundle bundle = new Bundle();
        // 存储当前位置
        bundle.putInt(SELX, selX);
        bundle.putInt(SELY, selY);
        bundle.putParcelable(VIEW_STATE, p);
        Log.d(TAG, "selX:" + selX + " selY:" + selY + " saved");
        return p;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        Bundle bundle = (Bundle) state;
        // 恢复当前位置
        select(bundle.getInt(SELX), bundle.getInt(SELY));
        Log.d(TAG, "selX:" + bundle.getInt(SELX) + " selY:" + bundle.getInt(SELX) + " restored");
        super.onRestoreInstanceState(bundle.getParcelable(VIEW_STATE));
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = (w - borderLeftSize * 2) / 9f;
        height = width;
        getRect(selX, selY, selRect);
        Log.d(TAG, "onSizeChanged width:" + w + " height:" + h);
    }

    private void getRect(int x, int y, Rect rect) {
        rect.set((int) (borderLeftSize + selX * width + 5), (int) (borderTopSize + selY * height + 5),
                (int) (borderLeftSize + selX * width + width - 2), (int) (borderTopSize + selY * height + height - 2));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // draw the background
        Paint background = new Paint();
        background.setColor(getResources().getColor(R.color.puzzle_background));
        canvas.drawRect(borderLeftSize, borderTopSize, borderLeftSize + width * 9, borderTopSize + height * 9, background);

        drawGuide(canvas);//绘制辅助背景

        // draw the board
        Paint light = new Paint();
        light.setColor(getResources().getColor(R.color.puzzle_light));

        Paint hilite = new Paint();
        hilite.setColor(getResources().getColor(R.color.puzzle_hilite));

        Paint dark = new Paint();
        dark.setStrokeWidth(3);
        dark.setColor(getResources().getColor(R.color.puzzle_dark));

        //绘制次要网格线（）
        for (int i = 0; i < 10; i++) {
            //横线
            canvas.drawLine(borderLeftSize, borderTopSize + i * height,
                    borderLeftSize + width * 9, borderTopSize + i * height, light);
            canvas.drawLine(borderLeftSize, borderTopSize + i * height + 1,
                    borderLeftSize + width * 9, borderTopSize + i * height + 1, hilite);
            //坚线
            canvas.drawLine(borderLeftSize + i * width, borderTopSize,
                    borderLeftSize + i * width, borderTopSize + height * 9, light);
            canvas.drawLine(borderLeftSize + i * width + 1, borderTopSize,
                    borderLeftSize + i * width + 1, borderTopSize + height * 9, hilite);
        }

        //绘制主网格线 ()
        for (int i = 0; i < 10; i++) {
            if (i % 3 != 0)
                continue;
            canvas.drawLine(borderLeftSize, borderTopSize + i * height,
                    borderLeftSize + width * 9, borderTopSize + i * height, dark);
            canvas.drawLine(borderLeftSize, borderTopSize + i * height + 1,
                    borderLeftSize + width * 9, borderTopSize + i * height + 1, hilite);

            canvas.drawLine(borderLeftSize + i * width, borderTopSize,
                    borderLeftSize + i * width, borderTopSize + height * 9, dark);
            canvas.drawLine(borderLeftSize + i * width + 1, borderTopSize,
                    borderLeftSize + i * width + 1, borderTopSize + height * 9, hilite);
        }


        // Draw the numbers
        Paint foreground = new Paint(Paint.ANTI_ALIAS_FLAG);
        foreground.setColor(getResources().getColor(R.color.puzzle_foreground));
        foreground.setStyle(Style.FILL);
        foreground.setTextSize(height * 0.75f);
        // foreground.setTextScaleX(width / height);
        foreground.setTextAlign(Align.CENTER);
        FontMetrics metrics = foreground.getFontMetrics();
        float x = width / 2;
        float y = (height - metrics.ascent - metrics.descent) / 2;
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                PieceBean pieceBean = game.getPieceBean(i, j);
                switch (pieceBean.getType()) {
                    case 0://原始数据-黑色
                        foreground.setColor(getResources().getColor(R.color.puzzle_foreground));
                        break;
                    case 1://填充数据-蓝色
                        foreground.setColor(0xff0000ff);
                        break;
                    case 2://测试数据-红色
                        foreground.setColor(0xffffff00);
                        break;
                    default:
                }
                canvas.drawText(game.getPieceString(i, j),
                        borderLeftSize + i * width + x, borderTopSize + j * height + y,
                        foreground);
            }
        }

        //绘制输入选项
        drawFun(canvas, background, light, hilite);

//        if (Prefs.getHints(getContext())) {//设置了提示功能
//            // Draw the hint
//            Paint hint = new Paint();
//            Rect r = new Rect();
//            int[] c = {getResources().getColor(R.color.puzzle_hint_0),
//                    getResources().getColor(R.color.puzzle_hint_1),
//                    getResources().getColor(R.color.puzzle_hint_2)};
//            int movesLeft;
//            for (int i = 0; i < 9; i++) {
//                for (int j = 0; j < 9; j++) {
//                    movesLeft = 9 - game.getUsedTiles(i, j).length;
//                    if (movesLeft < c.length) {
//                        getRect(i, j, r);
//                        hint.setColor(c[movesLeft]);
//                        canvas.drawRect(r, hint);
//                    }
//                }
//            }
//        }


    }

    /**
     * 绘制十字辅助背景
     */
    private void drawGuide(Canvas canvas) {
        int padding = 3;
        Paint selection = new Paint();
        selection.setStrokeWidth(5);
        selection.setColor(getResources().getColor(R.color.puzzle_selected));
        int pieceNum = game.getPieceNum(selX, selY);
        if (pieceNum != 0) {
            canvas.drawRect(selRect, selection);

            HashMap<Integer, Integer> numToXy = game.getNumToXy(pieceNum);
            for (int key : numToXy.keySet()) {
                canvas.drawRect(borderLeftSize + key * width, borderTopSize + numToXy.get(key) * height,
                        borderLeftSize + (key + 1) * width, borderTopSize + (numToXy.get(key) + 1) * height,
                        selection);
                //横线
                canvas.drawLine(borderLeftSize, borderTopSize + numToXy.get(key) * height + height / 2,
                        borderLeftSize + width * 9, borderTopSize + numToXy.get(key) * height + height / 2,
                        selection);
                //竖线
                canvas.drawLine(borderLeftSize + key * width + width / 2, borderTopSize,
                        borderLeftSize + key * width + width / 2, borderTopSize + 9 * height,
                        selection);
            }
        } else {
            //绘制坐标数字互斥区域
            //区块
            int startX = (int) (borderLeftSize + selX / 3 * 3 * width) + padding;
            int startY = (int) (borderTopSize + selY / 3 * 3 * height) + padding;
            int endX = (int) (startX + 3 * width - padding * 2);
            int endY = (int) (startY + 3 * height - padding * 2);
            canvas.drawRect(startX, startY, endX, endY, selection);
            //竖向
            canvas.drawRect(borderLeftSize + selX * width + padding, borderTopSize + padding,
                    borderLeftSize + (selX + 1) * width - padding, borderTopSize + 9 * height - padding,
                    selection);
            //横向
            canvas.drawRect(borderLeftSize + padding, borderTopSize + selY * height + padding,
                    borderLeftSize + 9 * width - padding, borderTopSize + (selY + 1) * height - padding,
                    selection);
        }
    }

    /**
     * 绘制输入选项
     *
     * @param canvas
     * @param background
     * @param light
     * @param hilite
     */
    private void drawFun(Canvas canvas, Paint background, Paint light, Paint hilite) {
        for (int i = 0; i < 3; i++) {//背景
            float startXVal = borderLeftSize + (i % 2 == 0 ? 2 : 3) * width;
            float startYVal = borderTopSize + height * 9 + (i + 1) * funTop + i * height;
            float endXVal = borderLeftSize + (i % 2 == 0 ? 7 : 6) * width;
            float endYVal = borderTopSize + height * 9 + (i + 1) * funTop + i * height + height;
            canvas.drawRect(startXVal, startYVal,
                    endXVal, endYVal,
                    background);
        }


        for (int i = 0; i < 6; i++) {//边框 5-3-5
            //横线
            float startXVal = borderLeftSize + (i / 2 == 1 ? 3 : 2) * width;
            float startYVal = borderTopSize + height * 9 + (i / 2 + 1) * funTop + (i + 1) / 2 * height;
            float endXVal = borderLeftSize + (i / 2 == 1 ? 6 : 7) * width;
            float endYVal = borderTopSize + height * 9 + (i / 2 + 1) * funTop + (i + 1) / 2 * height;

            canvas.drawLine(startXVal, startYVal, endXVal, endYVal, light);
            canvas.drawLine(startXVal, startYVal + (i % 2 == 0 ? +1 : -1),
                    endXVal, endYVal + (i % 2 == 0 ? +1 : -1), hilite);
            if (i % 2 == 0) {
                for (int k = 0; k < 6; k++) {//竖线
                    if (i / 2 == 1 && k > 3) continue;
                    canvas.drawLine(startXVal + k * width, startYVal,
                            startXVal + k * width, startYVal + height, light);
                    canvas.drawLine(startXVal + k * width + 1, startYVal,
                            startXVal + k * width + 1, startYVal + height, hilite);
                }
            }
        }

        Paint foreground = new Paint(Paint.ANTI_ALIAS_FLAG);
        foreground.setColor(getResources().getColor(R.color.puzzle_foreground));
        foreground.setStyle(Style.FILL);
        foreground.setTextSize(height * 0.75f);
        foreground.setTextAlign(Align.CENTER);
        FontMetrics metrics = foreground.getFontMetrics();
        float x = width / 2;
        float y = (height - metrics.ascent - metrics.descent) / 2;

        //绘制选项
        String[][] options = {{"1", "2", "3", "4", "5"}, {"", "?", "+", "-", ""}, {"6", "7", "8", "9", "0"}};
        for (int i = 0; i < 3; i++) {
            for (int k = 0; k < 5; k++) {
                float startXVal = borderLeftSize + 2 * width + k * width;
                float startYVal = borderTopSize + height * 9 + (i + 1) * funTop + i * height;
                canvas.drawText(options[i][k],
                        startXVal + x, startYVal + y,
                        foreground);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() != MotionEvent.ACTION_DOWN)
            return super.onTouchEvent(event);
        //棋盘的触发事件
        if (event.getX() > borderLeftSize && event.getX() < getWidth() - borderLeftSize &&
                event.getY() > borderTopSize && event.getY() < borderTopSize + height * 9
        ) {
            select((int) ((event.getX() - borderLeftSize) / width), (int) ((event.getY() - borderTopSize) / height));
        }
        //输入选项区域
        float widthStart = borderLeftSize + 2 * width;
        float widthEnd = borderLeftSize + 7 * width;
        float height1Start = borderTopSize + 9 * height + funTop;
        float height1End = borderTopSize + 9 * height + funTop + height;
        float height2Start = borderTopSize + 9 * height + 3 * funTop + 2 * height;
        float height2End = borderTopSize + 9 * height + 3 * funTop + 3 * height;

        if (event.getX() > widthStart && event.getX() < widthEnd) {
            if (event.getY() > height1Start && event.getY() < height1End) {//1-5
                int num = (int) ((event.getX() - borderLeftSize) / width) - 1;
                setSelectedTile(num);
            }
            if (event.getY() > height2Start && event.getY() < height2End) {//6-0
                int num = (int) ((event.getX() - borderLeftSize) / width) + 4;
                setSelectedTile(num > 9 ? 0 : num);
            }
        }
        Log.d(TAG, "onTouchEvent:" + event.getX() + ":" + event.getY());
        return true;
    }

    /**
     * 选取方块
     *
     * @param x
     * @param y
     */
    private void select(int x, int y) {
        invalidate(selRect);
        selX = (x + 9) % 9;
        selY = (y + 9) % 9;
        getRect(selX, selY, selRect);
        invalidate(selRect);

        Log.d(TAG, "select:" + x + "-" + "=" + y + "--" + selX + " " + selY);
    }

    /**
     * 选中填数字
     *
     * @param tile
     */
    public void setSelectedTile(int tile) {
        if (game.setTileIfValid(selX, selY, tile)) {
            invalidate();
        } else {//冲突时抖动提示
            Log.d(TAG, "setSelectedTile: invalid: " + tile);
            startAnimation(AnimationUtils.loadAnimation(game, R.anim.shake));
        }
    }
}
